home *** CD-ROM | disk | FTP | other *** search
- ' Heightmap demo 6
- '
- ' Flying around!
- '
- const heightScale# = 10 ' Height map scale factor
- const texScale# = 0.1 ' Number of textures per grid square
- const viewRange = 50 ' Number of cells visible
- dim xSize, ySize
- dim xMask, yMask ' bitmasks to apply to X and Y coordinates
- dim file ' File handle
- dim x, y ' Working variables
- dim texture ' OpenGL texture handle for our texture
- dim tx#, ty# ' Texture coordinates
- dim a#(2), b#(2), c#(2), d#(2), norm#(2) ' Temporary vectors used for lighting
- dim intensity#
- dim cameraMatrix#(3)(3) ' Camera position
- dim cameraPos#(3)
- dim startX, startY, start#(3) ' Start of viewable grid range
- dim inputX#, inputY#
-
- goto Start
-
- '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
- ' Routines
- CheckError:
- ' Check for file error
- if FileError () <> "" then
- print FileError ()
- CloseFile (file)
- end
- endif
- return
-
- '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
- ' Main program stars here
- Start:
-
- ' Open file
- file = OpenFileRead ("Files\Hills01.dat")
- ' Note: Basic4GL will only open files in the "files" subfolder of the folder
- ' where the program is saved.
- gosub CheckError
-
- ' Read X and Y size
- xSize = Val (ReadLine (file))
- ySize = Val (ReadLine (file))
- gosub CheckError
-
- ' Now that size is known, we can dim our 2D array
- dim h#(xSize - 1)(ySize - 1)
- xMask = xSize - 1
- yMask = ySize - 1
-
- for y = 0 to ySize - 1
- for x = 0 to xSize - 1
- h#(x)(y) = val (ReadText (file, true)) * heightScale#
- gosub CheckError
- next
- next
- CloseFile (file)
-
- ' Create light map
- dim lightSource#(2)
- lightSource# = vec3(0, -1, 0) ' Light shines straight down.
- lightSource# = Normalize (lightSource#) ' Light source must be length 1
-
- ' Create light map
- dim l# (xSize - 1)(ySize - 1)
- for x = 0 to xSize - 1
- for y = 0 to ySize - 1
- a# = vec3 (x, h#(x)(y), y)
- b# = vec3 (x+1, h#((x+1) and xMask)(y), y)
- c# = vec3 (x , h#(x )((y+1) and yMask), y+1)
- d# = vec3 (x+1, h#((x+1) and xMask)((y+1) and yMask), y+1)
-
- norm# = Normalize (CrossProduct (d# - a#, b# - c#))
-
- intensity# = norm# * -lightSource#
-
- intensity# = intensity# * intensity# * intensity#
- if intensity# < 0.2 then intensity# = 0.2 endif
-
- l#(x)(y) = intensity#
- next
- next
-
- ' Load texture file
- texture = LoadMipmapTexture ("textures\00005.jpg")
-
- ' Enable texture mapping, and bind our texture
- glEnable (GL_TEXTURE_2D)
- glBindTexture (GL_TEXTURE_2D, texture)
-
- ' Setup fog
- glEnable (GL_FOG)
- glFogi (GL_FOG_MODE, GL_LINEAR)
- glFogf (GL_FOG_START, viewRange * .3)
- glFogf (GL_FOG_END, viewRange * .8)
- glFogfv (GL_FOG_COLOR, vec4 (0, 0, 0, 1))
-
- glEnable (GL_CULL_FACE)
- ' "Cull face" is a speed optimisation that tells OpenGL not to draw any
- ' polygons that are facing away from the camera.
- ' The order that the polygon points are drawn in determines which way
- ' the polygon is said to be facing.
- ' When the polygon is facing towards the camera, all its points must
- ' be in anti-clockwise order.
-
- ' Set camera's start position
- cameraMatrix# = MatrixRotateY (45)
- cameraPos# = vec4 (0, 10, 0, 1)
- ' The camera is a little bit complicated to explain.
- ' We represent it as a rotation matrix, and a position vector.
-
- ' Text instructions
- TextMode (TEXT_OVERLAID)
- locate 4, 4: print "Use the arrow keys to fly around"
-
- while true
-
- ' Clear the screen
- glClear (GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
-
- ' Setup camera transformation
-
- ' To draw the scene relative to the camera, we create a rotation and translation
- ' matrix that describes the CAMERA RELATIVE TO THE SCREEN
- ' We then INVERT the matrix, which describes the SCREEN RELATIVE TO THE CAMERA.
- ' We load that matrix into OpenGL, which then replaces all the OpenGL transformations.
- glLoadMatrixf (RTInvert (MatrixTranslate (cameraPos#(0), cameraPos#(1), cameraPos#(2)) * cameraMatrix#))
- ' RTInvert is a simple matrix inversion function that ONLY works
- ' on matrices that are rotations, translations, or some combination
- ' of the two.
-
- ' We now figure out which part of the grid to draw by finding a square area
- ' immediately in front of the camera.
- start# = cameraPos# + cameraMatrix# * vec4 (0, 0, -viewRange / 2, 1)
- startX = start# (0) - viewRange / 2.0
- startY = start# (2) - viewRange / 2.0
-
- ' Draw the grid area
- for x = startX to startX + viewRange - 1
- for y = startY to startY + viewRange - 1
-
- ' Calculate the texture coordinates
- tx# = x * texScale#
- ty# = y * texScale#
-
- ' Draw a grid square.
- glBegin (GL_QUADS)
-
- ' By "and"ing the coordinates with the xMask or yMask, we
- ' are clamping them to that range, giving the map an infinite
- ' wrap-around effect.
-
- intensity# = l#(x and xMask)(y and yMask)
- glColor3f (intensity#, intensity#, intensity#)
- glTexCoord2f (tx# , ty#)
- glVertex3f (x , h#(x and xMask )(y and yMask ), y )
-
- intensity# = l#(x and xMask)(y+1 and yMask)
- glColor3f (intensity#, intensity#, intensity#)
- glTexCoord2f (tx# , ty# + texScale#)
- glVertex3f (x , h#(x and xMask )(y+1 and yMask), y+1)
-
- intensity# = l#(x+1 and xMask)(y+1 and yMask)
- glColor3f (intensity#, intensity#, intensity#)
- glTexCoord2f (tx# + texScale#, ty# + texScale#)
- glVertex3f (x+1, h#(x+1 and xMask)(y+1 and yMask), y+1)
-
- intensity# = l#(x+1 and xMask)(y and yMask)
- glColor3f (intensity#, intensity#, intensity#)
- glTexCoord2f (tx# + texScale#, ty#)
- glVertex3f (x+1, h#(x+1 and xMask)(y and yMask ), y )
- glEnd ()
- next
- next
-
- ' Draw the text instructions
- DrawText ()
-
- ' Show the result
- SwapBuffers ()
-
- ' Animation
- while SyncTimer (20)
-
- ' Move camera around
-
- ' Rotate the camera by multiplying more rotations into the camera rotation matrix.
- inputX# = 0
- inputY# = 0
- if ScanKeyDown (VK_LEFT) then inputX# = inputX# + 1 endif
- if ScanKeyDown (VK_RIGHT) then inputX# = inputX# - 1 endif
- if ScanKeyDown (VK_UP) then inputY# = inputY# - 1 endif
- if ScanKeyDown (VK_DOWN) then inputY# = inputY# + 1 endif
- cameraMatrix# = MatrixRotateY (cameraMatrix# (0)(1) * 0.4) * cameraMatrix# * MatrixRotateZ (inputX#) * MatrixRotateX (inputY#)
- cameraMatrix# = Orthonormalize (cameraMatrix#)
- ' All these multiplications can produce rounding errors, which can eventually build up
- ' and do weird things.
- ' Therefore we call Orthonormalize, which ensures that the rotation matrix is orthonormal
- ' (meaning it is a proper rotation matrix.)
-
- cameraPos# = cameraPos# + cameraMatrix# * vec4 (0, 0, -.1, 1)
- ' Move the camera forward, by multiplying the forward vector (0, 0, -.1) by the
- ' cameras rotation matrix, and adding it to the position
- wend
- wend